package com.ytf.dogbox.util;

import android.annotation.SuppressLint;

/**
 * author:tiwolf
 * create date:2021/11/30
 * Describe:
 */
public class IEEE754 {

    /**
     * 这个方法是IEEE754标准（浮点数转四字节）,公式转换 这个是详细的各项参数
     * @param is32Bit
     * @param number
     */
    public static void recalculate(boolean is32Bit,double number) {
//        double number;
        long digits, sign, exponent, mantissa;
//        try {
//            number = Double.parseDouble(((EditText) findViewById(R.id.number)).getText().toString());
//        } catch (NumberFormatException ex) {
//            // Reset on invalid number
//            number = 0;
//        }

        digits = is32Bit ? // Get the binary representation
                Float.floatToRawIntBits((float) number) :
                Double.doubleToRawLongBits(number);

        sign = is32Bit ? // first bit
                ((digits >>> 32 - 1) & 0b1)
                : ((digits >>> 64 - 1) & 0b1);

        exponent = is32Bit ?
                ((digits >>> 32 - 1 - 8) & 0b11111111) : // next 8 bits
                ((digits >>> 64 - 1 - 11) & 0b11111111111); // next 11 bits

        mantissa = is32Bit ?
                (digits & 0x7fffff) : // last 23 bits
                (digits & 0x1fffffffffffffl); // last 53 bits

        // Sign
        String signStr = (sign == 1 ? "-1" : "+1") + "\n"
                + Long.toBinaryString(sign);


        // Exponent w/ bias
        int expBias = is32Bit ? 127 : 1023;
        String expStr = (exponent + " - " + expBias + "= " + (exponent - expBias)) + "\n"
                // Pad binary string
                + String.format("%" + (is32Bit ? 8 : 11) + "s",
                Long.toBinaryString(exponent)).replace(' ', '0');


        // Mantissa
        double unshiftedMantissa = is32Bit ?
                (Float.intBitsToFloat((0b1111111 << 23) | ((int) mantissa)))
                : (Double.longBitsToDouble((0b1111111111l << 52) | mantissa));

        String manStr = (unshiftedMantissa) + "\n"
                // Pad binary string
                + String.format("%" + (is32Bit ? 23 : 52) + "s",
                Long.toBinaryString(mantissa)).replace(' ', '0');

        String binaryStr=is32Bit ?
                String.format("%32s", Integer.toBinaryString(Float.floatToRawIntBits((float) number))).replace(' ', '0')
                : String.format("%64s", Long.toBinaryString(Double.doubleToRawLongBits(number))).replace(' ', '0');

        String hexRep=is32Bit ?
                String.format("%8s", Integer.toHexString(Float.floatToRawIntBits((float) number))).replace(' ', '0')
                : String.format("%16s", Long.toHexString(Double.doubleToRawLongBits(number))).replace(' ', '0');


    }

    /**
     * @Desc: IEEE754标准（浮点数转四字节）,公式转换  例如：235.34396 转成 436B580E
     * @param num  float浮点值
     * @return
     */
    public static String float2HexIeee(float num){
        String hexStr=String.format("%8s", Integer.toHexString(Float.floatToRawIntBits(num))).replace(' ', '0');
        return hexStr;
    }



    /**
     * IEEE754标准（四字节转浮点数）,公式转换  {67，107，88，14}返回值为235.34396
     * @param hex 输入的是字节数组的值  步骤为：字节数组的值---每两个16进制转10进制---10进制转二进制---二进制进行计算值---得到IEEE754标准浮点值
     * @return
     */
    public static float hex2FloatIeee(byte[] hex){
//        String hexStr = bytesToHex(hex);
//        Log.e("tiwolf", "hex2FloatIeee: 得到的值为="+hexStr );
        StringBuilder binaryStr = new StringBuilder();
//        for(int i=0;i< hexStr.length();i+=2){
//            String a = hexStr.substring(i,i+2);
//            int c = Integer.parseInt(a,16);
//            @SuppressLint("DefaultLocale") String item = String.format("%08d",Integer.parseInt(Integer.toBinaryString(c)));
//            binaryStr.append(item);
//        }
        //这个是直接将字节数组的值直接计算，免去字节数组的值先转16进制，再转回来的麻烦
        for (int i = 0; i < hex.length; i++) {
            @SuppressLint("DefaultLocale")String byteItem="";
            if (hex[i]<0){
                byteItem = String.format("%08d",Integer.parseInt(Integer.toBinaryString((hex[i]+256))));
            }else {
                byteItem = String.format("%08d",Integer.parseInt(Integer.toBinaryString(hex[i])));
            }
            binaryStr.append(byteItem);
        }

        int n =  Integer.parseInt(binaryStr.substring(1,9),2);
        String mStr = binaryStr.substring(9,binaryStr.length()-1);
        double sum = 0;
        for(int i =1;i<=mStr.length();i++){
            if(mStr.charAt(i-1)=='1'){
                sum = sum+Math.pow(0.5,i);
            }
        }
        float v = (float) ((Math.pow(2, n - 127)) * (1 + sum));
        return v;
    }

    /**
     * IEEE754标准（四字节转浮点数）,公式转换
     * @param hexStr 这个是直接使用string  436B580E 返回值为235.34396
     * @return 返回浮点值
     */
    public static float hexStr2FloatIeee(String hexStr){
        hexStr=hexStr.replaceAll(" ","");
        StringBuilder binaryStr = new StringBuilder();
        for(int i=0;i< hexStr.length();i+=2){
            String a = hexStr.substring(i,i+2);
            int c = Integer.parseInt(a,16);
            @SuppressLint("DefaultLocale") String item = String.format("%08d",Integer.parseInt(Integer.toBinaryString(c)));
            binaryStr.append(item);
        }
        int n =  Integer.parseInt(binaryStr.substring(1,9),2);
        String mStr = binaryStr.substring(9,binaryStr.length()-1);
        double sum = 0;
        for(int i =1;i<=mStr.length();i++){
            if(mStr.charAt(i-1)=='1'){
                sum = sum+Math.pow(0.5,i);
            }
        }
        float v = (float) ((Math.pow(2, n - 127)) * (1 + sum));
        return v;
    }

    /**
     * 把16进制字符串转换成字节数组的值 例如：输入436B580E所对应的输出值为{67,107,88,14}
     * @param hex 输入字符串
     * @return byte[]
     */
    public static byte[] hexStringToByte(String hex) {
        int len = (hex.length() / 2);
        byte[] result = new byte[len];
        char[] achar = hex.toCharArray();
        for (int i = 0; i < len; i++) {
            int pos = i * 2;
            result[i] = (byte) (toByte(achar[pos]) << 4 | toByte(achar[pos + 1]));
        }
        return result;
    }

    private static int toByte(char c) {
        byte b = (byte) "0123456789ABCDEF".indexOf(c);
        return b;
    }


    /**
     * 字节数组的值 转回 16进制字符串  例如：输入{67，107，88，14}返回值为436B580E
     * @param bytes 字节数组的值
     * @return
     */
    private static String bytesToHex(byte[] bytes) {
        StringBuilder sbuffer = new StringBuilder();
        for (byte aByte : bytes) {
            String hex = Integer.toHexString(aByte & 0xFF);
            if (hex.length() < 2) {
                sbuffer.append(0);
            }
            sbuffer.append(hex);
        }
        return sbuffer.toString();
    }

}
